﻿using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using OAuthApp.Data;
using Swashbuckle.AspNetCore.Annotations;
using System;
using OAuthApp.Filters;
using Microsoft.AspNetCore.Authorization;
using OAuthApp.Tenant;
using OAuthApp.ApiModels.AppUsersController;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using OAuthApp.Services;
using System.Collections.Generic;
using System.Web;
using System.Text;
using ServiceStack;
using System.IO;
using ServiceStack.Text;
using System.Composition;

namespace OAuthApp.Apis
{
    [SwaggerTag("应用用户")]
    [ServiceFilter(typeof(ApiRequestLoggingAttribute))]
    public class AppUsersController : BaseController
    {
        private readonly AppDbContext _context;
        private readonly TokenProvider _tokenProvider;
        private readonly IMemoryCache _cache;
        private readonly static Random _random = new Random();

        public AppUsersController(AppDbContext context,
             TokenProvider tokenProvider,
            IHttpContextAccessor contextAccessor,
            TenantDbContext tenantContext,
            IMemoryCache cache)
        {
            _context = context;
            _tokenProvider = tokenProvider;
            _tenant = contextAccessor.HttpContext.GetTenantContext();
            _tenantContext = tenantContext;
            _cache = cache;
        }

        [HttpGet]
        [SwaggerOperation(OperationId = "AppUsers")]
        [EncryptResultFilter]
        public IActionResult List(long appId,
            string userName,
            string email,
            string phone,
            string platform,
            string unionId,
            int skip, int take)
        {
            var q = _context.AppUsers.AsQueryable();

            if (appId > 0)
            {
                q = q.Where(x => x.AppID == appId);
            }

            if (!string.IsNullOrWhiteSpace(userName))
            {
                userName = HttpUtility.UrlDecode(userName);

                q = q.Where(x => x.UserName.Contains(userName));
            }

            if (!string.IsNullOrWhiteSpace(email))
            {
                q = q.Where(x => x.Email.Equals(email));
            }

            if (!string.IsNullOrWhiteSpace(phone))
            {
                q = q.Where(x => x.Phone.Equals(phone));
            }

            if (!string.IsNullOrWhiteSpace(platform))
            {
                q = q.Where(x => x.Platform.Equals(platform));
            }

            if (!string.IsNullOrWhiteSpace(unionId))
            {
                q = q.Where(x => x.UnionID.Equals(unionId));
            }

            var total = q.Count();
            var data = q.OrderByDescending(x => x.ID).Skip(skip).Take(take).ToList();

            return OK(new
            {
                total,
                data
            });
        }

        [HttpGet("{id}")]
        [SwaggerOperation(OperationId = "AppUser")]
        [EncryptResultFilter]
        public IActionResult Get(long id)
        {
            var result = _context.AppUsers
                .FirstOrDefault(x => x.ID == id);

            if (result == null)
            {
                return NotFound();
            }

            return OK(result);
        }

        [HttpPut("{id}")]
        [SwaggerOperation(OperationId = "AppUserPut")]
        public IActionResult Put(long id, AppUser appUser)
        {
            if (id != appUser.ID)
            {
                return NotFound();
            }

            _context.Entry(appUser).State = EntityState.Modified;

            try
            {
                _context.SaveChanges();
            }
            catch (Exception ex)
            {
                return Error(ex.Message);
            }

            return OK(true);
        }

        [HttpDelete("{id}")]
        [SwaggerOperation(OperationId = "AppUserDelete")]
        public IActionResult Delete(long id)
        {
            var result = _context.AppUsers
                .FirstOrDefault(x => x.ID == id);

            if (result == null)
            {
                return NotFound();
            }

            _context.AppUsers.Remove(result);

            _context.SaveChanges();

            return OK(true);
        }

        [HttpGet("{appId}/Export")]
        [SwaggerOperation(OperationId = "AppUsersExport")]
        [ApiExplorerSettings(IgnoreApi = true)]
        public IActionResult Export(long appId)
        {
            var sql = @"SELECT 
Platform as 平台,
UnionID,
NickName 昵称,
Avatar 头像,
Data 备注,
UserName 账号,
Pwd	密码,
Email 邮箱,
EmailIsValid 邮箱是否验证,	
Phone 手机,
PhoneIsValid 手机是否验证,	
DATETIME(CreateDate) 注册时间,
DATETIME(LastUpdate) 最后更新
FROM AppUsers
WHERE AppID = " + appId;

            var data = _context.Query<ExportModel>(sql);

            var csvData = data.ToCsv();

            var csvBytes = Encoding.UTF8.GetBytes(csvData);

            var csvResult = new FileContentResult(csvBytes, "text/csv");

            csvResult.FileDownloadName = DateTime.UtcNow.AddHours(8).ToString("yyyyMMddHHMMss") + ".csv";

            return csvResult;
        }

        [HttpPost("{appId}/Import")]
        [SwaggerOperation(OperationId = "AppUsersImport")]
        public IActionResult Import(long appId, [FromQuery]bool check,[FromForm]IFormFile file)
        {
            if (file.Length < 1)
            {
                return Error("没有任何内容");
            }

            var sb = new StringBuilder();

            //sb.AppendLine("平台,UnionID,昵称,头像,备注,账号,密码,邮箱,邮箱是否验证,手机,手机是否验证,注册时间,最后更新");

            using (var reader = new StreamReader(file.OpenReadStream()))
            {
                // var lineNumber = 0;

                while (reader.Peek() >= 0)
                {
                    var LineContent = reader.ReadLine();
                    // lineNumber++;
                    // 第一行表头直接跳过
                    //if (lineNumber == 1) { continue; }

                    if (string.IsNullOrWhiteSpace(LineContent))
                    {
                        continue;
                    }
                    sb.AppendLine(LineContent);
                }
            }

            JsConfig<string>.DeSerializeFn = str =>
            {
                if (!string.IsNullOrWhiteSpace(str)) { return str.Trim(); }

                return "";
            };

            var users = new List<AppUser>();

            try
            {
                var importUsers = CsvSerializer.DeserializeFromString<List<ExportModel>>(sb.ToString());

                if (check)
                {
                    var report = new List<string>();

                    for (var i = 0; i < importUsers.Count; i++)
                    {
                        if (string.IsNullOrWhiteSpace(importUsers[i].账号) &&
                            (
                                string.IsNullOrWhiteSpace(importUsers[i].UnionID) ||
                                string.IsNullOrWhiteSpace(importUsers[i].平台)
                            ))
                        {
                            report.Add($"第{i + 1}行，账号 / unionId+平台，必须2选1。");
                        }

                        else if (!string.IsNullOrWhiteSpace(importUsers[i].账号))
                        {
                            if (_context.AppUsers.Any(q => q.AppID == AppID && q.UserName == importUsers[i].账号))
                            {
                                report.Add($"第{i + 1}行，账号已存在。");
                            }
                        }

                        else if (_context.AppUsers.Any(q =>
                        q.AppID == AppID && q.Platform == importUsers[i].平台 &&
                        q.UnionID == importUsers[i].UnionID))
                        {
                            report.Add($"第{i + 1}行，{importUsers[i].平台}，unionId已存在。");
                        }
                    }

                    return OK(report);
                 }
                else
                {
                    importUsers.ForEach(x =>
                    {
                        if (string.IsNullOrWhiteSpace(x.账号) &&
                             (
                                 string.IsNullOrWhiteSpace(x.UnionID) ||
                                 string.IsNullOrWhiteSpace(x.平台)
                             ))
                        {
                            return;
                        }

                        else if (!string.IsNullOrWhiteSpace(x.账号))
                        {
                            if (_context.AppUsers.Any(q => q.AppID == AppID && q.UserName == x.账号))
                            {
                                return;
                            }
                        }

                        else if (_context.AppUsers.Any(q => q.AppID == AppID && q.Platform == x.平台 && q.UnionID == x.UnionID))
                        {
                            return;
                        }

                        var userItem = new AppUser()
                        {
                            UserName = x.账号,
                            AppID = appId,
                            Avatar = x.头像,
                            Data = x.备注,
                            Email = x.邮箱,
                            IsDelete = false,
                            NickName = x.昵称,
                            Phone = x.手机,
                            Platform = x.平台,
                            Pwd = x.密码,
                            UnionID = x.UnionID,
                            UserID = 0L,
                        };

                        if (DateTime.TryParse(x.注册时间, out DateTime dt)) { userItem.CreateDate = dt; }
                        if (DateTime.TryParse(x.最后更新, out DateTime dt2)) { userItem.LastUpdate = dt2; }
                        if (bool.TryParse(x.手机是否验证, out bool verify)) { userItem.PhoneIsValid = verify; }
                        if (bool.TryParse(x.邮箱是否验证, out bool verify2)) { userItem.EmailIsValid = verify2; }

                        users.Add(userItem);

                    });

                    _context.AppUsers.AddRange(users);

                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                return Error("读取文件失败，数据格式错误。" + ex.Message);
            }

            return OK(true);
        }

        [HttpDelete("{appId}/Clear")]
        [SwaggerOperation(OperationId = "AppUsersClear")]
        public IActionResult Clear(long appId)
        {
            try
            {
                _context.Execute("DELETE FROM AppUsers WHERE AppID = " + appId);
            }
            catch (Exception ex)
            {
                return Error(ex.Message);
            }

            return OK(true);
        }

        //#region 手机
        //#region 手机登录
        //[HttpPost("MobileSignIn")]
        //[SwaggerOperation(OperationId = "AppUserMobileSignIn")]
        //[AllowAnonymous]
        //public IActionResult MobileSignIn(MobileSignInRequest value)
        //{
        //    if (!ExistsApp(value.AppID))
        //    {
        //        return Error("不存在的应用");
        //    }

        //    var appUser = _context.AppUsers.FirstOrDefault(x =>
        //    x.AppID == value.AppID && x.Phone == value.Phone);

        //    if (appUser == null)
        //    {
        //        return Error("用户不存在");
        //    }

        //    var code = _cache.Get<string>("mobile_" + value.VerifyCode);

        //    if (string.IsNullOrWhiteSpace(code))
        //    {
        //        return Error("验证码错误或已过期");
        //    }

        //    var result = CreateToken(new TenantUserModel()
        //    {
        //        Avatar = appUser.Avatar,
        //        Email = appUser.Email,
        //        ID = appUser.ID,
        //        Mobile = appUser.Phone,
        //        Name = appUser.UserName,
        //        NickName = appUser.NickName,
        //        Role = UserConst.DefaultAppUserRole
        //    }, value.AppID);

        //    return OK(result);
        //} 
        //#endregion

        //#region 发送手机验证码
        //[HttpPost("SendMobileVerifyCode")]
        //[SwaggerOperation(OperationId = "AppUserSendMobileVerifyCode")]
        //[AllowAnonymous]
        //public IActionResult SendMobileVerifyCode(MobileSignInRequest value)
        //{
        //    if (!ExistsApp(value.AppID))
        //    {
        //        return Error("不存在的应用");
        //    }

        //    var appUser = _context.AppUsers.FirstOrDefault(x =>
        //    x.AppID == value.AppID && x.Phone == value.Phone);

        //    if (appUser == null)
        //    {
        //        return Error("用户不存在");
        //    }

        //    var verifyCode = _random.Next(111111, 999999);

        //    _cache.Set("mobile_" + verifyCode.ToString(),
        //        "true",
        //        new DateTimeOffset(DateTime.Now.AddMinutes(5)));

        //    return OK(true);
        //}
        //#endregion

        //#region 手机注册
        //[HttpPost("MobileSignUp")]
        //[SwaggerOperation(OperationId = "AppUserMobileSignUp")]
        //[AllowAnonymous]
        //public IActionResult MobileSignUp(MobileSignUpRequest value)
        //{
        //    if (!ExistsApp(value.AppID))
        //    {
        //        return Error("不存在的应用");
        //    }

        //    if (_context.AppUsers.Any(x => x.AppID == value.AppID && x.Phone == value.Phone))
        //    {
        //        return Error("账号已存在");
        //    }

        //    var code = _cache.Get<string>("mobile_" + value.VerifyCode);

        //    if (string.IsNullOrWhiteSpace(code))
        //    {
        //        return Error("验证码错误或已过期");
        //    }

        //    var user = CreateUser(new CreateUserModel()
        //    {
        //        AppID = value.AppID,
        //        Avatar = value.Avatar,
        //        Email = "",
        //        NickName = value.Phone,
        //        Phone = value.Phone,
        //        Platform = value.Platform,
        //        Pwd = value.Pwd,
        //        UserName = value.Phone,
        //        UnionID = "",
        //        EmailIsValid = false,
        //        PhoneIsValid = true
        //    }, 0);

        //    var result = CreateToken(user, value.AppID);

        //    return OK(result);
        //}
        //#endregion
        //#endregion

        //#region 邮箱
        //#region 邮箱注册
        //[HttpPost("EmailSignUp")]
        //[SwaggerOperation(OperationId = "AppUserEmailSignUp")]
        //[AllowAnonymous]
        //public IActionResult EmailSignUp(EmailSignUpRequest value)
        //{
        //    if (!ExistsApp(value.AppID))
        //    {
        //        return Error("不存在的应用");
        //    }

        //    if (_context.AppUsers.Any(x => x.AppID == value.AppID && x.Email == value.Email))
        //    {
        //        return Error("账号已存在");
        //    }

        //    var code = _cache.Get<string>("email_" + value.VerifyCode);

        //    if (string.IsNullOrWhiteSpace(code))
        //    {
        //        return Error("验证码错误或已过期");
        //    }

        //    var user = CreateUser(new CreateUserModel()
        //    {
        //        AppID = value.AppID,
        //        Avatar = value.Avatar,
        //        Email = value.Email,
        //        NickName = value.Email,
        //        Phone = "",
        //        Platform = value.Platform,
        //        Pwd = value.Pwd,
        //        UserName = value.Email,
        //        UnionID = "",
        //        EmailIsValid = true,
        //        PhoneIsValid = false
        //    }, 0);

        //    var result = CreateToken(user, value.AppID);

        //    return OK(result);
        //}
        //#endregion

        //#region 邮箱登录
        //[HttpPost("SignInByEmail")]
        //[SwaggerOperation(OperationId = "AppUserEmailSignIn")]
        //[AllowAnonymous]
        //public IActionResult EmailSignIn(EmailSignInRequest value)
        //{
        //    if (!ExistsApp(value.AppID))
        //    {
        //        return Error("不存在的应用");
        //    }

        //    var appUser = _context.AppUsers.FirstOrDefault(x =>
        //    x.AppID == value.AppID && x.Email == value.Email);

        //    if (appUser == null)
        //    {
        //        return Error("用户不存在");
        //    }

        //    var code = _cache.Get<string>("email_" + value.VerifyCode);

        //    if (string.IsNullOrWhiteSpace(code))
        //    {
        //        return Error("验证码错误或已过期");
        //    }

        //    var result = CreateToken(new TenantUserModel()
        //    {
        //        Avatar = appUser.Avatar,
        //        Email = appUser.Email,
        //        ID = appUser.ID,
        //        Mobile = appUser.Phone,
        //        Name = appUser.UserName,
        //        NickName = appUser.NickName,
        //        Role = UserConst.DefaultAppUserRole
        //    }, value.AppID);

        //    return OK(result);
        //} 
        //#endregion

        //#region 发送邮箱验证码
        //[HttpPost("SendEmailVerifyCode")]
        //[SwaggerOperation(OperationId = "AppUserSendEmailVerifyCode")]
        //[AllowAnonymous]
        //public IActionResult SendEmailVerifyCode(EmailSignInRequest value)
        //{
        //    if (!ExistsApp(value.AppID))
        //    {
        //        return Error("不存在的应用");
        //    }

        //    var appUser = _context.AppUsers.FirstOrDefault(x =>
        //    x.AppID == value.AppID && x.Email == value.Email);

        //    if (appUser == null)
        //    {
        //        return Error("用户不存在");
        //    }

        //    var verifyCode = _random.Next(111111, 999999);

        //    _cache.Set("email_" + verifyCode.ToString(),
        //        "true",
        //        new DateTimeOffset(DateTime.Now.AddMinutes(5)));

        //    return OK(true);
        //}
        //#endregion
        //#endregion

        #region UnionID
        #region UnionID登录
        [HttpPost("UnionIDSignIn")]
        [SwaggerOperation(OperationId = "AppUserUnionIDSignIn")]
        [AllowAnonymous]
        public IActionResult UnionIDSignIn(UnionIDSignInRequest value)
        {
            if (!ExistsApp(value.AppID))
            {
                return Error("不存在的应用");
            }

            AppUser appUser = null;

            try
            {
                appUser = _context.AppUsers.FirstOrDefault(x =>
                 x.AppID == value.AppID &&
                 x.UnionID == value.UnionID &&
                 x.Platform == value.Platform);
            }
            catch (ArgumentException ex)
            {
                return Error(ex.Message);
            }

            if (appUser == null)
            {
                return Error("用户不存在");
            }

            var UModel = new TenantUserModel()
            {
                Avatar = appUser.Avatar,
                Email = appUser.Email,
                ID = appUser.ID,
                Mobile = appUser.Phone,
                Name = appUser.UserName,
                NickName = appUser.NickName
            };

            UModel.Role.Add(UserConst.DefaultAppUserRole);

            var result = CreateToken(UModel, value.AppID);

            return OK(result);
        }
        #endregion

        #region UnionID注册
        [HttpPost("UnionIDSignUp")]
        [SwaggerOperation(OperationId = "AppUserUnionIDSignUp")]
        [AllowAnonymous]
        public IActionResult UnionIDSignUp(UnionIDSignUpRequest value)
        {
            if (!ExistsApp(value.AppID))
            {
                return Error("不存在的应用");
            }

            if (_context.AppUsers.Any(x => x.AppID == value.AppID &&
            x.Platform == value.Platform && x.UnionID == value.UnionID))
            {
                return Error("账号已存在");
            }

            var user = CreateUser(new CreateUserModel()
            {
                AppID = value.AppID,
                Avatar = value.Avatar,
                Email = "",
                NickName = value.NickName,
                Phone = "",
                Platform = value.Platform,
                Pwd = value.Pwd,
                UserName = "",
                UnionID = value.UnionID,
                EmailIsValid = false,
                PhoneIsValid = false
            }, 0);

            var result = CreateToken(user, value.AppID);

            return OK(result);
        }
        #endregion
        #endregion

        #region 账号密码
        #region 登录
        [HttpPost("SignIn")]
        [SwaggerOperation(OperationId = "AppUserSignIn")]
        [AllowAnonymous]
        public IActionResult SignIn(SignInRequest value)
        {
            if (!ExistsApp(value.AppID))
            {
                return Error("不存在的应用");
            }

            AppUser appUser = null;

            try
            {
                appUser = _context.AppUsers.FirstOrDefault(x =>
                 x.AppID == value.AppID &&
                 x.UserName == value.UserName);
            }
            catch (ArgumentException ex)
            {
                return Error(ex.Message);
            }

            if (appUser == null)
            {
                return Error("用户不存在");
            }

            else if (!AppFunctions.md5Compare(value.Pwd, appUser.Pwd))
            {
                return Error("密码错误");
            }

            var UModel = new TenantUserModel()
            {
                Avatar = appUser.Avatar,
                Email = appUser.Email,
                ID = appUser.ID,
                Mobile = appUser.Phone,
                Name = appUser.UserName,
                NickName = appUser.NickName
            };

            UModel.Role.Add(UserConst.DefaultAppUserRole);

            var result = CreateToken(UModel, value.AppID);

            return OK(result);
        }
        #endregion

        #region 注册
        [HttpPost("SignUp")]
        [SwaggerOperation(OperationId = "AppUserSignUp")]
        [AllowAnonymous]
        public IActionResult SignUp(SignUpRequest value)
        {
            if (!ExistsApp(value.AppID))
            {
                return Error("不存在的应用");
            }

            if (_context.AppUsers.Any(x => x.AppID == value.AppID && x.UserName == value.UserName))
            {
                return Error("账号已存在");
            }

            var user = CreateUser(new CreateUserModel()
            {
                AppID = value.AppID,
                Avatar = value.Avatar,
                Email = "",
                NickName = value.NickName,
                Phone = "",
                Platform = value.Platform,
                Pwd = value.Pwd,
                UserName = value.UserName,
                UnionID = "",
                EmailIsValid = false,
                PhoneIsValid = false
            }, 0);

            var result = CreateToken(user, value.AppID);

            return OK(result);
        }
        #endregion
        #endregion

        #region 微信小程序
        #region 网页登录
        [HttpPost("QRCodeSignIn")]
        [SwaggerOperation(OperationId = "AppUserQRCodeSignIn")]
        [AllowAnonymous]
        public IActionResult QRCodeSignIn(QRCodeSignInRequest value)
        {
            if (!ExistsApp(value.AppID))
            {
                return Error("不存在的应用");
            }

            var item = _tenantContext.QRCodeSignIns.FirstOrDefault(x =>
            x.ChannelCode == ChannelCodes.App &&
            x.ChannelAppID == value.AppID.ToString() &&
            x.SignInKey == value.SignInKey);

            if (item == null)
            {
                return Error("二维码失效请刷新");
            }

            if (item.Status.Equals(QRCodeSignInStatus.PreSignIn))
            {
                return Error("请扫码");
            }

            if (item.Status.Equals(QRCodeSignInStatus.Scaned))
            {
                return Error("登陆中...");
            }

            var appUser = _context.AppUsers.FirstOrDefault(x => x.ID == item.AppUserID);

            if (appUser == null)
            {
                return Error("用户不存在");
            }

            var UModel = new TenantUserModel()
            {
                Avatar = appUser.Avatar,
                Email = appUser.Email,
                ID = appUser.ID,
                Mobile = appUser.Phone,
                Name = appUser.UserName,
                NickName = appUser.NickName
            };

            UModel.Role.Add(UserConst.DefaultAppUserRole);

            var result = CreateToken(UModel, value.AppID);

            return OK(result);
        }
        #endregion

        #region 注册
        [HttpPost("QRCodeSignUp")]
        [SwaggerOperation(OperationId = "AppUserQRCodeSignUp")]
        [AllowAnonymous]
        public IActionResult QRCodeSignUp(QRCodeSignUpRequest value)
        {
            if (!ExistsApp(value.AppID))
            {
                return Error("不存在的应用");
            }

            var item = _tenantContext.QRCodeSignIns.Where(x => x.TenantID == _tenant.Id &&
            x.ChannelCode == ChannelCodes.App &&
            x.ChannelAppID == value.AppID.ToString() &&
            x.SignInKey == value.SignInKey).FirstOrDefault();

            if (item == null || item.Status.Equals(QRCodeSignInStatus.PreSignIn))
            {
                return Error("二维码已失效，请刷新重试");
            }

            var appUser = _context.AppUsers.Where(x => x.AppID == value.AppID &&
            x.Platform == value.Platform &&
            x.UnionID == value.UnionID).FirstOrDefault();

            TenantUserModel user = null;

            if (appUser == null)
            {
               user = CreateUser(new CreateUserModel()
                {
                    AppID = value.AppID,
                    Avatar = value.Avatar,
                    Email = value.Email,
                    NickName = value.NickName,
                    Phone = value.Phone,
                    Platform = value.Platform,
                    Pwd = value.UnionID,
                    UserName = value.UserName,
                    UnionID = value.UnionID,
                    EmailIsValid = value.EmailIsValid,
                    PhoneIsValid = value.PhoneIsValid
                }, 0);

                item.AppUserID = user.ID;
                item.Status = QRCodeSignInStatus.OK;
                item.LastUpdate = DateTime.Now;
                _tenantContext.SaveChanges();
            }
            else
            {
                appUser.NickName = value.NickName;
                appUser.Avatar = value.Avatar;
                appUser.LastUpdate = DateTime.Now;
                _context.SaveChanges();

                user = new TenantUserModel()
                {
                    ID = appUser.ID,
                    Name = appUser.UserName,
                    NickName = appUser.NickName ?? "",
                    Email = appUser.Email ?? "",
                    Mobile = appUser.Phone ?? "",
                    Avatar = appUser.Avatar ?? ""
                };

                user.Role.Add(UserConst.DefaultAppUserRole);
            }

            var result = CreateToken(user, value.AppID);

            item.AppUserID = user.ID;
            item.Status = QRCodeSignInStatus.OK;
            item.LastUpdate = DateTime.Now;
            _tenantContext.SaveChanges();

            return OK(result);
        }
        #endregion

        #region 扫码通知
        [HttpPost("QRCodeScan")]
        [SwaggerOperation(OperationId = "AppUserQRCodeScan")]
        [AllowAnonymous]
        public IActionResult QRCodeScan(QRCodeScanRequest value)
        {
            var appItem = _context.Apps.Find(value.AppID);

            if (appItem == null)
            {
                return Error("不存在的应用");
            }

            var item = _tenantContext.QRCodeSignIns.Where(x => x.TenantID == _tenant.Id &&
            x.ChannelCode == ChannelCodes.App &&
            x.ChannelAppID == value.AppID.ToString() &&
            x.SignInKey == value.SignInKey).FirstOrDefault();

            if (item == null || !item.Status.Equals(QRCodeSignInStatus.PreSignIn))
            {
                return Error("二维码已失效，请刷新重试");
            }

            item.Status = QRCodeSignInStatus.Scaned;
            item.LastUpdate = DateTime.Now;
            _tenantContext.SaveChanges();

            return OK(new
            {
                AppID = appItem.ID,
                Name = appItem.Name,
                Logo = appItem.Logo,
                Website = appItem.Website,
                Description = appItem.Description,
                Tags = appItem.Tags,
                Scopes = item.Scopes,
                Remark = item.Remark
            });
        }
        #endregion

        #region 预登陆
        [HttpPost("QRCodePreSignIn")]
        [SwaggerOperation(OperationId = "AppUserQRCodePreSignIn")]
        [AllowAnonymous]
        public IActionResult QRCodePreSignIn(QRCodePreSignInRequest value)
        {
            if (!ExistsApp(value.AppID))
            {
                return Error("不存在的应用");
            }

            var props = PropSettings(_context,
                value.AppID,
                PropKeyConst.WechatMiniPClientID,
                PropKeyConst.WechatMiniPClientSecret);

            if (!props.ContainsKey(PropKeyConst.WechatMiniPClientID) ||
                !props.ContainsKey(PropKeyConst.WechatMiniPClientSecret))
            {
                return Error("应用未配置小程序参数");
            }

            var qrcodeSignInItem = new QRCodeSignIn()
            {
                ChannelCode = ChannelCodes.App,
                ChannelAppID = value.AppID.ToString(),
                TenantID = _tenant.Id,
                Scopes = value.Scopes,
                Remark = value.Remark
            };

            _tenantContext.QRCodeSignIns.Add(qrcodeSignInItem);

            _tenantContext.SaveChanges();

            return OK(qrcodeSignInItem.SignInKey);
        }
        #endregion
        #endregion

        #region 获取个人资料
        [HttpGet("Profile")]
        [SwaggerOperation(OperationId = "AppUserProfile")]
        public IActionResult Profile()
        {
            var appUser = _context.AppUsers.FirstOrDefault(x => x.ID == UserID);

            if (appUser == null)
            {
                return Error("不存在的用户");
            }

            return OK(new
            {
                appUser.AppID,
                appUser.Platform,
                appUser.UnionID,
                appUser.Phone,
                appUser.CreateDate,
                appUser.UserName,
                appUser.PhoneIsValid,
                appUser.Data,
                appUser.Email,
                appUser.EmailIsValid,
                appUser.LastUpdate,
                appUser.NickName,
                appUser.ID,
                appUser.Avatar,
                Role = UserConst.DefaultAppUserRole
            });
        }
        #endregion

        #region 更新个人资料
        [HttpPut("Profile")]
        [SwaggerOperation(OperationId = "AppUserUpdateProfile")]
        public IActionResult UpdateProfile(UpdateProfileRequest value)
        {
            var appUser = _context.AppUsers.FirstOrDefault(x => x.ID == UserID);

            if (appUser == null)
            {
                return Error("不存在的用户");
            }

            if (!string.IsNullOrWhiteSpace(value.NickName) && !value.NickName.Equals(appUser.NickName))
            {
                appUser.NickName = value.NickName;
            }

            if (!string.IsNullOrWhiteSpace(value.Avatar) && !value.Avatar.Equals(appUser.Avatar))
            {
                appUser.Avatar = value.Avatar;
            }

            if (appUser.Data == null || (!string.IsNullOrWhiteSpace(value.Data) && !value.Data.Equals(appUser.Data)))
            {
                appUser.Data = value.Data;
            }

            try
            {
                _context.SaveChanges();
            }
            catch (Exception ex)
            {
                return Error(ex.Message);
            }

            return OK(true);
        } 
        #endregion

        #region helper
        private bool ExistsApp(long appId)
        {
            return _context.Apps.Any(x => x.ID == appId && !x.IsDelete);
        }
        private TokenModel CreateToken(TenantUserModel user, long appId)
        {
            var claims = _tenant.CreateClaims(user, appId.ToString(), UserDataGroups.Client);

            var token = _tokenProvider.CreateToken(items =>
            {
                items.AddRange(claims);
            });

            return token;
        }
        private TenantUserModel CreateUser(CreateUserModel m,long userId)
        {
            var appUser = new AppUser()
            {
                Platform = m.Platform,
                UnionID = m.UnionID,
                UserID = userId,
                UserName = m.UserName,
                AppID = m.AppID,
                NickName = m.NickName,
                Avatar = m.Avatar,
                Phone = m.Phone,
                PhoneIsValid = m.PhoneIsValid,
                Email = m.Email,
                EmailIsValid = m.EmailIsValid,
                Pwd = AppFunctions.md5(m.Pwd)
            };

            _context.AppUsers.Add(appUser);

            _context.SaveChanges();

            var userModel = new TenantUserModel()
            {
                ID = appUser.ID,
                Name = m.UserName,
                NickName = m.NickName ?? "",
                Email = m.Email ?? "",
                Mobile = m.Phone ?? "",
                Avatar = m.Avatar ?? ""
            };

            userModel.Role.Add(UserConst.DefaultAppUserRole);

            return userModel;
        }
        #endregion
    }
}
